use std::collections::HashSet;

use salvo::{
    endpoint, handler,
    oapi::extract::{JsonBody, PathParam},
    Depot, Request, Response,
};

use crate::config::app_response::{ErrRes, Res};
use crate::extension::model::user::{ChangePasswordRequest, CreateUserRequest, User, UserListRequest};
use crate::services::user;
use crate::utils::user_util;
// #[endpoint(tags("comm"), )]
// pub async fn post_login(req: JsonBody<UserLoginRequest>, res: &mut Response) {
//     let result: AppResult<UserLoginResponse> = user::login(req.0).await;
//     match result {
//         Ok(data) => {
//             let jwt_token = data.token.clone();
//             let cookie = Cookie::build(("jwt_token", jwt_token))
//                 .path("/")
//                 .http_only(true)
//                 .build();
//             res.add_cookie(cookie);
//         }
//         Err(e) => ErrRes::with_err(&e.to_string()).into_response(res),
//     }
// }
//
// #[endpoint(tags("api.console.halo.run/v1alpha1/User"))]
// pub async fn post_add_user(req: JsonBody<UserAddRequest>, res: &mut Response) {
//     let result = user::add_user(req.0).await;
//     match result {
//         Ok(data) => Res::with_data(data).into_response(res),
//         Err(e) => ErrRes::with_err(&e.to_string()).into_response(res),
//     }
// }
//
// #[endpoint(tags("api.console.halo.run/v1alpha1/User"),
// parameters(
// ("id", description = "user id"),
// ))]
// pub async fn put_update_user(req: &mut Request, res: &mut Response) {
//     let req: UserUpdateRequest = req.extract().await.unwrap();
//     let result = user::update_user(req).await;
//     match result {
//         Ok(data) => Res::with_data(data).into_response(res),
//         Err(e) => ErrRes::with_err(&e.to_string()).into_response(res),
//     }
// }
//
// #[endpoint(tags("api.console.halo.run/v1alpha1/User"), )]
// pub async fn delete_user(id: PathParam<String>, res: &mut Response) {
//     let result = user::delete_user(id.0).await;
//     match result {
//         Ok(_) => Res::with_data(()).into_response(res),
//         Err(e) => ErrRes::with_err(&e.to_string()).into_response(res),
//     }
// }
//
// #[endpoint(tags("api.console.halo.run/v1alpha1/User"), )]
// pub async fn get_users(res: &mut Response) {
//     let result = user::users().await;
//     match result {
//         Ok(data) => Res::with_data(data).into_response(res),
//         Err(e) => ErrRes::with_err(&e.to_string()).into_response(res),
//     }
// }

/// Get current user detail
///
#[endpoint(tags("api.console.halo.run/v1alpha1/User"))]
pub async fn me(depot: &mut Depot, res: &mut Response) {
    let result = user::me(depot).await;
    match result {
        Ok(data) => Res::with_data(data).into_response(res),
        Err(e) => ErrRes::with_err(&e.to_string()).into_response(res),
    }
}

/// Get user detail by name
///
#[endpoint(tags("api.console.halo.run/v1alpha1/User"),
parameters(
("name", description = "User name"),
))]
pub async fn get_user_by_name(name: PathParam<String>, res: &mut Response) {
    let result = user::get_user_by_name(name.0).await;
    match result {
        Ok(data) => Res::with_data(data).into_response(res),
        Err(e) => ErrRes::with_err(&e.to_string()).into_response(res),
    }
}

/// Update current user profile, but password.
///
// #[endpoint(tags("api.console.halo.run/v1alpha1/User"), )]
#[handler]
pub async fn update_profile(req: JsonBody<User>, depot: &mut Depot, res: &mut Response) {
    let user: User = req.0;

    let result = user::update_profile(depot, user).await;
    match result {
        Ok(data) => Res::with_data(data).into_response(res),
        Err(e) => ErrRes::with_err(&e.to_string()).into_response(res),
    }
}

/// UpdateCurrentUser
/// Update current user profile, but password.
///
/// #[endpoint(tags("api.console.halo.run/v1alpha1/User"), )]
#[handler]
pub async fn grant_permission(
    name: PathParam<String>,
    req: JsonBody<HashSet<String>>,
    res: &mut Response,
) {
    let roles: HashSet<String> = req.0;

    let result = user::grant_roles(name.0, &roles).await;
    match result {
        Ok(data) => Res::with_data(data).into_response(res),
        Err(e) => ErrRes::with_err(&e.to_string()).into_response(res),
    }
}

/// CreateUser
/// Creates a new user.
///
/// #[endpoint(tags("api.console.halo.run/v1alpha1/User"), )]
#[handler]
pub async fn create_user(req: JsonBody<CreateUserRequest>, res: &mut Response) {
    let user: CreateUserRequest = req.0;

    let result = user::create_user(user).await;
    match result {
        Ok(data) => Res::with_data(data).into_response(res),
        Err(e) => ErrRes::with_err(&e.to_string()).into_response(res),
    }
}

/// GetPermissions
/// Get permissions of user
///
/// #[endpoint(tags("api.console.halo.run/v1alpha1/User"), )]
#[handler]
pub async fn get_user_permission(name: PathParam<String>, depot: &mut Depot, res: &mut Response) {
    let username = name.0;
    let result = user::get_user_permission(username, depot).await;
    match result {
        Ok(data) => Res::with_data(data).into_response(res),
        Err(e) => ErrRes::with_err(&e.to_string()).into_response(res),
    }
}

/// ChangePassword
/// Change password of user.
///
// #[handler]
#[endpoint(tags("api.console.halo.run/v1alpha1/User"))]
pub async fn change_password(
    name: PathParam<String>,
    req: JsonBody<ChangePasswordRequest>,
    depot: &mut Depot,
    res: &mut Response,
) {
    let username = name.0;
    let change_password_request = req.0;
    let current_user_name = user_util::current_username(depot);

    let result = user::change_password(username, current_user_name, change_password_request).await;
    match result {
        Ok(data) => Res::with_data(data).into_response(res),
        Err(e) => ErrRes::with_err(&e.to_string()).into_response(res),
    }
}

/// ListUsers
///
///  List users
///
#[endpoint(tags("UserV1alpha1Console"))]
pub async fn list(req: &mut Request, depot: &mut Depot, res: &mut Response) {
    let list_request: UserListRequest = req.parse_queries().unwrap();
    let result = user::list(list_request).await;
    match result {
        Ok(data) => Res::with_data(data).into_response(res),
        Err(e) => ErrRes::with_err(&e.to_string()).into_response(res),
    }
}

/// UploadUserAvatar
///
///  upload user avatar
///
#[endpoint(tags("UserV1alpha1Console"))]
pub async fn update_user_avatar(req: &mut Request, depot: &mut Depot, res: &mut Response) {
    let list_request: UserListRequest = req.parse_queries().unwrap();
    let result = user::list(list_request).await;
    match result {
        Ok(data) => Res::with_data(data).into_response(res),
        Err(e) => ErrRes::with_err(&e.to_string()).into_response(res),
    }
}
